﻿using DB2WORD.Models;
using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.SS.Formula.Functions;
using NPOI.XWPF.UserModel;

namespace DB2WORD.Logics
{
    public static class NpoiWord
    {
        public static Action<string>? MessageCallback;

        private static void Test()
        {
            var file = "001.docx";
            using(var dotStream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                XWPFDocument template = new XWPFDocument(dotStream);

                XWPFDocument document = new XWPFDocument();
                XWPFStyles newStyles = document.CreateStyles();
                newStyles.SetStyles(template.GetCTStyle());


                template.Close();
            }
        }

        public static async Task<Result> Export(string fileName, Project project, List<GroupInfo> groups, List<ChangeLog> logs)
        {
            try
            {
                MessageCallback?.Invoke("正在准备导出数据字典...");
                XWPFDocument document = new XWPFDocument();

                //XWPFStyles styles = document.CreateStyles();
                ////styles.SetEastAsia("Chinese");
                //string style1 = "FirstLvlStyle";
                //string style2 = "SecondLvlStyle";
                //string style3 = "ThirLvlStyle";

                //CT_Fonts ctFonts = new CT_Fonts();
                ////ctFonts.eastAsia = "Chinese";
                ////ctFonts.ascii = "Times New Roman";
                //styles.AddStyle(
                //    new XWPFStyle(
                //        new CT_Style()
                //        {
                //            styleId = style1,
                //            rPr = new CT_RPr() { rFonts = ctFonts, b = new CT_OnOff() { val = true }, szCs = new CT_HpsMeasure() { val = 24 } }, // gives val / 2 font size
                //        })
                // );
                //styles.AddStyle(
                //    new XWPFStyle(
                //        new CT_Style()
                //        {
                //            styleId = style2,
                //            rPr = new CT_RPr() { rFonts = ctFonts, b = new CT_OnOff() { val = true }, szCs = new CT_HpsMeasure() { val = 16 } }, // gives val / 2 font size
                //        })
                // );
                //styles.AddStyle(
                //    new XWPFStyle(
                //        new CT_Style()
                //        {
                //            styleId = style3,
                //            rPr = new CT_RPr() { rFonts = ctFonts, b = new CT_OnOff() { val = true }, szCs = new CT_HpsMeasure() { val = 12 } }, // gives val / 2 font size
                //        })
                // );

                XWPFNumbering numbering = document.CreateNumbering();
                var ct_abn = new CT_AbstractNum();
                var mlt = new CT_MultiLevelType();
                mlt.val = ST_MultiLevelType.multilevel;
                ct_abn.multiLevelType = mlt;
                ct_abn.lvl = new List<CT_Lvl> {
                    new CT_Lvl {
                        ilvl = "0", start = new CT_DecimalNumber() {val = "1"}, numFmt = new CT_NumFmt() {val = ST_NumberFormat.@decimal},
                        lvlText = new CT_LevelText() {val = "%1."}, lvlJc = new CT_Jc() {val = ST_Jc.left},
                        pPr = new CT_PPr {ind = new CT_Ind {left = "360", hanging = 360}},
                        rPr = new CT_RPr{b = new CT_OnOff {val = true}, szCs = new CT_HpsMeasure() {val = 36}}
                    },
                    new CT_Lvl {
                        ilvl = "1", start = new CT_DecimalNumber() {val = "1"}, numFmt = new CT_NumFmt() {val = ST_NumberFormat.@decimal},
                        lvlText = new CT_LevelText() {val = "%1.%2."}, lvlJc = new CT_Jc() {val = ST_Jc.left},
                        pPr = new CT_PPr {ind = new CT_Ind {left = "360", hanging = 360}},
                        rPr = new CT_RPr{b = new CT_OnOff {val = true}, szCs = new CT_HpsMeasure() {val = 32}}
                    },
                    new CT_Lvl {
                        ilvl = "2", start = new CT_DecimalNumber() {val = "1"}, numFmt = new CT_NumFmt() {val = ST_NumberFormat.@decimal},
                        lvlText = new CT_LevelText() {val = "%1.%2.%3."}, lvlJc = new CT_Jc() {val = ST_Jc.left},
                        pPr = new CT_PPr {ind = new CT_Ind {left = "360", hanging = 360}},
                        rPr = new CT_RPr{b = new CT_OnOff {val = true}, szCs = new CT_HpsMeasure() {val = 28}}
                    },
                };
                string abstractNumId = numbering.AddAbstractNum(new XWPFAbstractNum(ct_abn));
                string numId = numbering.AddNum(abstractNumId);

                document.SetPageHeader($"{project.Name}数据字典");
                document.SetPageFooter("快享医疗科技(上海)有限公司");
                document.WithEmptyParagraph(3);
                document.CreateParagraph($"{project.Name}数据字典", 20, ParagraphAlignment.CENTER, isBold: true);
                document.CreateParagraph($"版本：{project.Version}", 14, ParagraphAlignment.CENTER);
                document.CreateParagraph($"by：DB2WORD.exe", 14, ParagraphAlignment.CENTER);
                document.CreateParagraph(DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss"), 14, ParagraphAlignment.CENTER);

                if(logs != null && logs.Any())
                {
                    #region 变更历史
                    document.WithEmptyParagraph(2);
                    document.CreateParagraph($"变更说明", 16, isBold: true);

                    XWPFTable tableLogs = document.CreateTable(logs.Count + 1, 4);
                    tableLogs.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };
                    tableLogs.Width = 5250;//总宽度
                    tableLogs.WithColumnWidths(300, 800, 600, 3800);
                    var lrow = 0;
                    tableLogs.GetRow(lrow).Height = 30 * 12;
                    tableLogs.WithParagraph(lrow, 0, tableLogs.CreateParagraph("序号", ParagraphAlignment.CENTER, isBold: true));
                    tableLogs.WithParagraph(lrow, 1, tableLogs.CreateParagraph("版本", isBold: true));
                    tableLogs.WithParagraph(lrow, 2, tableLogs.CreateParagraph("日期", isBold: true));
                    tableLogs.WithParagraph(lrow, 3, tableLogs.CreateParagraph("说明", isBold: true));

                    foreach(var col in logs)
                    {
                        lrow++;
                        tableLogs.GetRow(lrow).Height = 30 * 12;
                        tableLogs.WithParagraph(lrow, 0, tableLogs.CreateParagraph(lrow.ToString(), ParagraphAlignment.CENTER));
                        tableLogs.WithParagraph(lrow, 1, tableLogs.CreateParagraph(col.Version.ToString()));
                        tableLogs.WithParagraph(lrow, 2, tableLogs.CreateParagraph(col.Date.ToString("yyyy-MM-dd")));
                        tableLogs.WithParagraph(lrow, 3, tableLogs.CreateParagraph(col.Description));
                    }
                    #endregion
                }

                document.WithNewPage();

                var totalCount = groups.Sum(x => x.Tables.Count);
                var currentIndex = 0;
                MessageCallback?.Invoke($"开始准备表格数据，共计表格{totalCount}个...");
                foreach(var grp in groups)
                {
                    document.WithEmptyParagraph();
                    document.CreateParagraph($"{grp.Name}", 16, isBold: true).SetNumID(numId, "0");
                    document.CreateParagraph($"表格数量：{grp.Tables.Count}", 9);

                    var levelSecond = 0;
                    foreach(var tbl in grp.Tables)
                    {
                        currentIndex++;
                        levelSecond++;
                        MessageCallback?.Invoke($"{currentIndex}/{totalCount}  开始处理表格 {tbl.Name} - 【{tbl.Label}】...");
                        document.WithEmptyParagraph();
                        document.CreateParagraph($"{tbl.Label}   {tbl.Name}", 14, isBold: true).SetNumID(numId, "1");
                        document.CreateParagraph(tbl.Description, 12);

                        #region 字段
                        document.CreateParagraph($"字段说明", 12, isBold: true).SetNumID(numId, "2");
                        XWPFTable tableColumns = document.CreateTable(tbl.Columns.Count + 1, 9);
                        tableColumns.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };
                        tableColumns.Width = 5250;//总宽度
                        tableColumns.WithColumnWidths(200, 700, 700, 700, 200, 200, 200, 700, 700);
                        int row = 0;
                        tableColumns.GetRow(row).Height = 30 * 12;

                        tableColumns.WithParagraph(row, 0, tableColumns.CreateParagraph("序号", ParagraphAlignment.CENTER, isBold: true));
                        tableColumns.WithParagraph(row, 1, tableColumns.CreateParagraph("字段", isBold: true));
                        tableColumns.WithParagraph(row, 2, tableColumns.CreateParagraph("名称", isBold: true));
                        tableColumns.WithParagraph(row, 3, tableColumns.CreateParagraph("类型", isBold: true));
                        tableColumns.WithParagraph(row, 4, tableColumns.CreateParagraph("可空", ParagraphAlignment.CENTER, isBold: true));
                        tableColumns.WithParagraph(row, 5, tableColumns.CreateParagraph("主键", ParagraphAlignment.CENTER, isBold: true));
                        tableColumns.WithParagraph(row, 6, tableColumns.CreateParagraph("自增", ParagraphAlignment.CENTER, isBold: true));
                        tableColumns.WithParagraph(row, 7, tableColumns.CreateParagraph("默认值", isBold: true));
                        tableColumns.WithParagraph(row, 8, tableColumns.CreateParagraph("备注", isBold: true));

                        foreach(var col in tbl.Columns)
                        {
                            row++;
                            tableColumns.GetRow(row).Height = 30 * 12;
                            tableColumns.WithParagraph(row, 0, tableColumns.CreateParagraph(col.Sort.ToString(), ParagraphAlignment.CENTER));
                            tableColumns.WithParagraph(row, 1, tableColumns.CreateParagraph(col.Name));
                            tableColumns.WithParagraph(row, 2, tableColumns.CreateParagraph(col.Label));
                            tableColumns.WithParagraph(row, 3, tableColumns.CreateParagraph(col.Type));
                            tableColumns.WithParagraph(row, 4, tableColumns.CreateParagraph(col.CanBeNull ? "√" : "", ParagraphAlignment.CENTER));
                            tableColumns.WithParagraph(row, 5, tableColumns.CreateParagraph(col.IsPrimary ? "√" : "", ParagraphAlignment.CENTER));
                            tableColumns.WithParagraph(row, 6, tableColumns.CreateParagraph(col.IsIdentity ? "√" : "", ParagraphAlignment.CENTER));
                            tableColumns.WithParagraph(row, 7, tableColumns.CreateParagraph(col.Default));
                            tableColumns.WithParagraph(row, 8, tableColumns.CreateParagraph(col.Description));
                        }

                        #endregion

                        #region 索引
                        document.WithEmptyParagraph();
                        document.CreateParagraph($"索引说明", 12, isBold: true).SetNumID(numId, "2");

                        XWPFTable tableIndexes = document.CreateTable(tbl.Indexes.Count + 1, 4);
                        tableIndexes.GetCTTbl().AddNewTblPr().tblLayout = new CT_TblLayoutType() { type = ST_TblLayoutType.@fixed };
                        tableIndexes.Width = 5250;//总宽度
                        tableIndexes.WithColumnWidths(200, 700, 700, 700);
                        row = 0;
                        tableIndexes.GetRow(row).Height = 30 * 12;
                        tableIndexes.WithParagraph(row, 0, tableIndexes.CreateParagraph("序号", ParagraphAlignment.CENTER, isBold: true));
                        tableIndexes.WithParagraph(row, 1, tableIndexes.CreateParagraph("名称", isBold: true));
                        tableIndexes.WithParagraph(row, 2, tableIndexes.CreateParagraph("列", isBold: true));
                        tableIndexes.WithParagraph(row, 3, tableIndexes.CreateParagraph("备注", isBold: true));

                        foreach(var col in tbl.Indexes)
                        {
                            row++;
                            tableIndexes.GetRow(row).Height = 30 * 12;
                            tableIndexes.WithParagraph(row, 0, tableIndexes.CreateParagraph(col.Sort.ToString(), ParagraphAlignment.CENTER));
                            tableIndexes.WithParagraph(row, 1, tableIndexes.CreateParagraph(col.Name));
                            tableIndexes.WithParagraph(row, 2, tableIndexes.CreateParagraph(col.Columns));
                            tableIndexes.WithParagraph(row, 3, tableIndexes.CreateParagraph(col.Description));
                        }
                        #endregion
                    }
                }

                MessageCallback?.Invoke($"全部{totalCount}个表格处理完成，正在导出文档...");
                using(var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                {
                    document.Write(stream);
                    document.Close();
                    MessageCallback?.Invoke($"导出文档 {fileName} 完成");
                    return Result.OK(fileName);
                }
            }
            catch(Exception ex)
            {
                return Result.Fail(ex.Message);
            }
        }
    }
}
